home *** CD-ROM | disk | FTP | other *** search
- //=============================================================================
- // SsaoBlur.hlsl by Frank Luna (C) 2011 All Rights Reserved.
- //
- // Performs a bilateral edge preserving blur of the ambient map. We use
- // a pixel shader instead of compute shader to avoid the switch from
- // compute mode to rendering mode. The texture cache makes up for some of the
- // loss of not having shared memory. The ambient map uses 16-bit texture
- // format, which is small, so we should be able to fit a lot of texels
- // in the cache.
- //=============================================================================
-
- cbuffer cbSsao : register(b0)
- {
- float4x4 gProj;
- float4x4 gInvProj;
- float4x4 gProjTex;
- float4 gOffsetVectors[14];
-
- // For SsaoBlur.hlsl
- float4 gBlurWeights[3];
-
- float2 gInvRenderTargetSize;
-
- // Coordinates given in view space.
- float gOcclusionRadius;
- float gOcclusionFadeStart;
- float gOcclusionFadeEnd;
- float gSurfaceEpsilon;
-
-
- };
-
- cbuffer cbRootConstants : register(b1)
- {
- bool gHorizontalBlur;
- };
-
- // Nonnumeric values cannot be added to a cbuffer.
- Texture2D gNormalMap : register(t0);
- Texture2D gDepthMap : register(t1);
- Texture2D gInputMap : register(t2);
-
- SamplerState gsamPointClamp : register(s0);
- SamplerState gsamLinearClamp : register(s1);
- SamplerState gsamDepthMap : register(s2);
- SamplerState gsamLinearWrap : register(s3);
-
- static const int gBlurRadius = 5;
-
- static const float2 gTexCoords[6] =
- {
- float2(0.0f, 1.0f),
- float2(0.0f, 0.0f),
- float2(1.0f, 0.0f),
- float2(0.0f, 1.0f),
- float2(1.0f, 0.0f),
- float2(1.0f, 1.0f)
- };
-
- struct VertexOut
- {
- float4 PosH : SV_POSITION;
- float2 TexC : TEXCOORD;
- };
-
- VertexOut VS(uint vid : SV_VertexID)
- {
- VertexOut vout;
-
- vout.TexC = gTexCoords[vid];
-
- // Quad covering screen in NDC space.
- vout.PosH = float4(2.0f*vout.TexC.x - 1.0f, 1.0f - 2.0f*vout.TexC.y, 0.0f, 1.0f);
-
- return vout;
- }
-
- float NdcDepthToViewDepth(float z_ndc)
- {
- // z_ndc = A + B/viewZ, where gProj[2,2]=A and gProj[3,2]=B.
- float viewZ = gProj[3][2] / (z_ndc - gProj[2][2]);
- return viewZ;
- }
-
- float4 PS(VertexOut pin) : SV_Target
- {
- // unpack into float array.
- float blurWeights[12] =
- {
- gBlurWeights[0].x, gBlurWeights[0].y, gBlurWeights[0].z, gBlurWeights[0].w,
- gBlurWeights[1].x, gBlurWeights[1].y, gBlurWeights[1].z, gBlurWeights[1].w,
- gBlurWeights[2].x, gBlurWeights[2].y, gBlurWeights[2].z, gBlurWeights[2].w,
- };
-
- float2 texOffset;
- if(gHorizontalBlur)
- {
- texOffset = float2(gInvRenderTargetSize.x, 0.0f);
- }
- else
- {
- texOffset = float2(0.0f, gInvRenderTargetSize.y);
- }
-
- // The center value always contributes to the sum.
- float4 color = blurWeights[gBlurRadius] * gInputMap.SampleLevel(gsamPointClamp, pin.TexC, 0.0);
- float totalWeight = blurWeights[gBlurRadius];
-
- float3 centerNormal = gNormalMap.SampleLevel(gsamPointClamp, pin.TexC, 0.0f).xyz;
- float centerDepth = NdcDepthToViewDepth(
- gDepthMap.SampleLevel(gsamDepthMap, pin.TexC, 0.0f).r);
-
- for(float i = -gBlurRadius; i <=gBlurRadius; ++i)
- {
- // We already added in the center weight.
- if( i == 0 )
- continue;
-
- float2 tex = pin.TexC + i*texOffset;
-
- float3 neighborNormal = gNormalMap.SampleLevel(gsamPointClamp, tex, 0.0f).xyz;
- float neighborDepth = NdcDepthToViewDepth(
- gDepthMap.SampleLevel(gsamDepthMap, tex, 0.0f).r);
-
- //
- // If the center value and neighbor values differ too much (either in
- // normal or depth), then we assume we are sampling across a discontinuity.
- // We discard such samples from the blur.
- //
-
- if( dot(neighborNormal, centerNormal) >= 0.8f &&
- abs(neighborDepth - centerDepth) <= 0.2f )
- {
- float weight = blurWeights[i + gBlurRadius];
-
- // Add neighbor pixel to blur.
- color += weight*gInputMap.SampleLevel(
- gsamPointClamp, tex, 0.0);
-
- totalWeight += weight;
- }
- }
-
- // Compensate for discarded samples by making total weights sum to 1.
- return color / totalWeight;
- }
-